


#if !defined(_BoundaryConditionsTest_)
#define _BoundaryConditionsTest_

#include <src/miscellaneous/OS_basic.h>
#include <src/math/BoundaryCondition/BoundaryCondition.h>
#include <src/test/data/data_test.h>

template<class data, std::size_t Dim = data::Dim, typename Boundary = data::Boundary_type>
struct boundary_conditions_example {
	boundary_conditions_example() {
		OS_STATIC_CHECK(false); // you have to implement this test
	};
};

template<class data>
struct boundary_conditions_example<data,1,Periodic> {
	boundary_conditions_example() {
		std::cout << std::endl << " ---------------------------------------------------" << std::endl;
		std::cout << std::endl << " --Starting boundary_conditions_example 1D for " << data::get_name() << std::endl;
		array_test<data>();
		data(4);
		for (OS_int i = 0; i<A.size(1);++i)
				A[i] = i;
		std::cout << std::endl << std::endl << " Access Memory for " << A << std::endl;
		std::cout << std::endl << " A[4] should be A [0] : " << A [4];
		bool logical = A[4] == A[0];
		OS_DYNAMIC_CHECK(logical == true, "boundary_conditions_example : A[4] == A[0] failed ");
		std::cout << std::endl << " A[-1] should be A [3] : " << A [-1];
		bool logical = A[-1] == A[3];
		OS_DYNAMIC_CHECK(logical == true, "boundary_conditions_example : A[-1] == A[3] failed ");
		std::cout << std::endl << " --End boundary_conditions_example 1D for " << data::get_name() << std::endl;
	};
};


template<class data>
struct boundary_conditions_example<data,1,Protected> {
	boundary_conditions_example() {
		std::cout << std::endl << " ---------------------------------------------------" << std::endl;
		std::cout << std::endl << " --Starting boundary_conditions_example 1D for " << data::get_name() << Protected::get_name()<< std::endl;
		array_test<data>();
		data A(4);
		for (OS_int i = 0; i<A.size();++i)
				A[i] = i;
		std::cout << std::endl << std::endl << " Access Memory for " << A << std::endl;
		std::cout << std::endl << " A[4] should raise an exception : " ;
		bool logical = false;
		try {
			A[4] = 0;
		}
		catch (...) {
			logical = true;
		};
		OS_DYNAMIC_CHECK(logical == true, "exception raising  A[4] failed ");
		logical = false;
		std::cout << std::endl << " A[-1] should raise an exception : " ;
		try {
			A[-1] = 0;
		}
		catch (...) {
			logical = true;
		};
		OS_DYNAMIC_CHECK(logical == true, "exception raising  A[4] failed ");
		std::cout << std::endl << " --End boundary_conditions_example 1D for " << data::get_name() << Protected::get_name()<< std::endl;
	};
};

template<class data>
struct boundary_conditions_example<data,2,Periodic> {
	boundary_conditions_example() {
		std::cout << std::endl << " --Starting boundary_conditions_example 2D for " << data::get_name() << Protected::get_name() << std::endl;
		typedef typename data::value_type array_1;
		boundary_conditions_example<array_1>();
		array_test<data>();

		data B(3,4);

		for (OS_int i = 0; i<B.size(2);++i) {
			for (OS_int j = 0; j<B.size(1);++j) {
					B[i][j] = i+j;
			};
		};
		std::cout << std::endl << std::endl << " Access Memory for " << B << std::endl;
		std::cout << std::endl << " B[3] should be B[0] : " << B [3];
		bool logical = B[3] == B[0];
		OS_DYNAMIC_CHECK(logical == true, "boundary_conditions_example : B[3] == A[0]] failed ");
		std::cout << std::endl << " B[-1] should be B [2] : " << B [-1];
		logical = B[-1] == B[2];
		OS_DYNAMIC_CHECK(logical == true, "boundary_conditions_example : B[-1] == B[2]] failed ");
		std::cout << std::endl << " --End boundary_conditions_example 2D for " << data::get_name() << Protected::get_name() << std::endl;
	};
};
template<class data>
struct boundary_conditions_example<data,2,Protected> {
	boundary_conditions_example() {
		std::cout << std::endl << " ---------------------------------------------------" << std::endl;
		std::cout << std::endl << " --Starting boundary_conditions_example 2D for " << data::get_name() << Protected::get_name() << std::endl;
		typedef typename data::value_type array_1;
		boundary_conditions_example<array_1>();
		array_test<data>();
		data B(3,4);
		for (OS_int i = 0; i<B.size(2);++i) {
			for (OS_int j = 0; j<B.size(1);++j) {
					B[i][j] = i+j;
			};
		};

		std::cout << "Two dimensional dimensional OS_Vector B(4,3)" << B << std::endl;
		std::cout << std::endl << " B[3] should raise an exception : " ;
		bool logical = false;
		try {
			B[3];
		}
		catch (...) {
			logical = true;
		};
		OS_DYNAMIC_CHECK(logical == true, "exception raising  B[3] failed ");
		logical = false;
		std::cout << std::endl << " B[-1] should raise an exception : " ;
		try {
			B[-1];
		}
		catch(...) {
			logical = true;
		};
		OS_DYNAMIC_CHECK(logical == true, "exception raising  B[-1] failed ");
		std::cout << " --End boundary_conditions_example 2D for " << data::get_name() << Protected::get_name() << std::endl;
	};
};

template<class data>
struct boundary_conditions_example<data,3,Periodic> {
	boundary_conditions_example() {
		std::cout << std::endl << " ---------------------------------------------------" << std::endl;
		std::cout << std::endl << " --Starting boundary_conditions_example 3D for " << data::get_name() << Periodic::get_name() << std::endl;
		typedef typename data::value_type array_2;
		typedef typename array_2::value_type array_1;
		boundary_conditions_example<array_1>();
		boundary_conditions_example<array_2>();
		array_test<data>();

		data C = fill_data<data,3>()();

		
		std::cout << "Three dimensional dimensional Periodic C(2,3,4)" << C << std::endl;
		std::cout << std::endl << std::endl << " Access Memory test";
		std::cout << std::endl << " C[2] should be C[0] : " << C [2];
		bool logical = C[2] == C[0];
		OS_DYNAMIC_CHECK(logical == true, "boundary_conditions_example: C[2] = C[0] failed ");

		std::cout << std::endl << " C[-1] should be C[1] : " << C [-1];
		logical = C[-1] == C[1];
		OS_DYNAMIC_CHECK(logical == true, "boundary_conditions_example: C[-1] = C[1] failed ");
		std::cout << std::endl << " --End boundary_conditions_example 3D for " << data::get_name() << Periodic::get_name() << std::endl;
	};
};







template<class data>
struct boundary_conditions_example<data,1,Dirichlet> {
	boundary_conditions_example() {
		std::cout << std::endl << " ---------------------------------------------------" << std::endl;
		std::cout << std::endl << " --Starting boundary_conditions_example 2D for " << data::get_name() << Dirichlet::get_name() << std::endl;
		array_test<data>();
		data A(4);
		for (OS_int i = 0; i<A.size(1);++i)
				A[i] = i;
		std::cout << std::endl << std::endl << " Access Memory for " << A << std::endl;
		std::cout << std::endl << " A[4] should be 0 : " << A [4];
		bool logical = A[4] == 0;
		OS_DYNAMIC_CHECK(logical == true, "boundary_conditions_example : A[4] == 0 failed ");
		std::cout << std::endl << " A[-1] should be 0 : " << A [-1];
		logical = A[-1] == 0;
		OS_DYNAMIC_CHECK(logical == true, "boundary_conditions_example : A[-1] == 0 failed ");
		std::cout << std::endl << " --End boundary_conditions_example 2D for " << data::get_name() << Dirichlet::get_name() << std::endl;
	};
};

template<class data>
struct boundary_conditions_example<data,2,Dirichlet> {
	boundary_conditions_example() {
		std::cout << std::endl << " --Starting boundary_conditions_example 2D for " << data::get_name() << Dirichlet::get_name() << std::endl;
		typedef typename data::value_type array_1;
		boundary_conditions_example<array_1>();
		array_test<data>();

		array_1 A(4);
		A.assign(0);

		data B = fill_data<data,2>()();

		std::cout << std::endl << std::endl << " Access Memory for " << B << std::endl;
		std::cout << std::endl << " B[3] should be 0 : " << B [3];
		bool logical = B[3] == A;
		OS_DYNAMIC_CHECK(logical == true, "boundary_conditions_example : B[3] == 0 failed ");
		std::cout << std::endl << " B[-1] should be 0 : " << B[-1];
		logical = B[-1] == A;
		OS_DYNAMIC_CHECK(logical == true, "boundary_conditions_example : B[-1] == 0 failed ");
		std::cout << std::endl << " --End boundary_conditions_example 2D for " << data::get_name() << Dirichlet::get_name() << std::endl;
	};
};



void boundary_test();

#endif
